package com.wlf.server.im;

import cn.dev33.satoken.stp.StpUtil;
import com.wlf.server.common.entity.ImChatRecord;
import com.wlf.server.common.entity.SysAttachment;
import com.wlf.server.common.service.ImChatRecordService;
import com.wlf.server.common.service.SysAttachmentService;
import com.wlf.server.common.service.SysUserService;
import com.wlf.server.common.ws.NioWebSocketChannelPool;
import com.wlf.server.common.ws.WsBean;
import com.wlf.server.im.dto.ImConst;
import com.wlf.server.im.dto.ImMappingDTO;
import com.wlf.server.im.dto.ImUser;
import com.wlf.server.im.dto.MsgBody;
import com.wlf.server.web.util.AjaxBean;
import com.wlf.server.web.util.JSON;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class ImService {
    @Resource
    private SysAttachmentService attachmentService;
    @Resource
    private ImMappingDTO imMappingDTO;
    @Resource
    private SysUserService userService;
    @Resource
    private ImChatRecordService imChatRecordService;
    @Resource
    private NioWebSocketChannelPool webSocketChannelPool;

    private static final String imAttrRemark = "在线聊天";

    /**
     * 返回在线好友
     */
    public AjaxBean online(){
        String thisUserId = StpUtil.getLoginIdAsString();
        // 在线用户的ID
        Set<String> onlineIds = webSocketChannelPool.getBindUserMap().keySet();

        List<ImUser> imUsers = imMappingDTO.toImUser(userService.list());
        for (ImUser imUser : imUsers) {
            if (onlineIds.stream().anyMatch(i -> i.equals(imUser.getId()))) {
                imUser.setUserStatus(ImConst.UserStatus.online);
            } else {
                imUser.setUserStatus(ImConst.UserStatus.leave);
            }
        }
        // 不显示自己，没意义
        imUsers = imUsers.stream().filter(i -> !i.getId().equals(thisUserId)).toList();

        for (ImUser imUser : imUsers) {
            List<ImChatRecord> list = imChatRecordService.lambdaQuery()
                    .eq(ImChatRecord::getSendUserId,imUser.getId())
                    .eq(ImChatRecord::getReceiveUserId, thisUserId)
                    .orderByDesc(ImChatRecord::getId)
                    .list();
            imUser.setLastMsg("暂无消息！");
            if (list.size() > 0){
                ImChatRecord record = list.get(0);
                imUser.setLastSendTime(record.getSendTime().format(DateTimeFormatter.ofPattern("HH:mm")));
                MsgBody msgBody = JSON.parseObject(record.getMsgBody(), MsgBody.class);
                switch (msgBody.getMsgType()){
                    case text ->  imUser.setLastMsg(msgBody.getMsgContent());
                    case img ->  imUser.setLastMsg("图片消息");
                }
            }
            // 未读消息数量
            imUser.setNoReadNum((int) list.stream().filter(i -> !i.getReading()).count());
        }
        // 历史图片
        List<String> historyImg = attachmentService.lambdaQuery()
                .eq(SysAttachment::getRemark, imAttrRemark)
                .eq(SysAttachment::getCreateBy,thisUserId)
                .select(SysAttachment::getWebPath)
                .orderByDesc(SysAttachment::getId)
                .list().stream().map(SysAttachment::getWebPath).toList();
        return AjaxBean.getOkData(imUsers).set("historyImg",historyImg);
    }


    /**
     * 发送文字消息
     * @param userId 给指定ID谁发消息
     * @param msg 发送消息内容
     * @return 发送结果
     */
    public AjaxBean send(String userId, String msg,MsgBody.MsgType type){
        // 保存聊天记录
        ImChatRecord chatRecord = new ImChatRecord();
        chatRecord.setSendTime(LocalDateTime.now());
        chatRecord.setSendUserId(StpUtil.getLoginIdAsString());
        chatRecord.setReceiveUserId(userId);
        MsgBody body = new MsgBody();
        body.setId(chatRecord.getId());
        body.setMsgType(type);
        body.setMsgContent(msg);
        chatRecord.setMsgBody(JSON.toJSONString(body));
        // 保存
        imChatRecordService.save(chatRecord);
        // 往浏览器推送消息
        //无需发送数据过去，
        // 只需发个响应过去，然后在请求后端，类似于，和浏览器说声，我给发消息了，你用Ajax收一下。
        webSocketChannelPool.sendToUser(userId, WsBean.get(WsBean.CallBackEm.receive_msg));
        return AjaxBean.getOkData(body);
    }
    /**
     * 发送图片消息
     * @param file 文件
     * @param userId 发给谁
     * @return  发送结果
     */
    public AjaxBean uploadSendImg(MultipartFile file, String userId){
        SysAttachment attachment = attachmentService.plus(file, imAttrRemark);
        ImChatRecord chatRecord = new ImChatRecord();
        chatRecord.setSendTime(LocalDateTime.now());
        chatRecord.setSendUserId(StpUtil.getLoginIdAsString());
        chatRecord.setReceiveUserId(userId);
        MsgBody body = new MsgBody();
        body.setId(chatRecord.getId());
        body.setMsgType(MsgBody.MsgType.img);
        body.setMsgContent(attachment.getWebPath());
        chatRecord.setMsgBody(JSON.toJSONString(body));
        // 保存
        imChatRecordService.save(chatRecord);
        // 往浏览器推送消息
        //无需发送数据过去，
        // 只需发个响应过去，然后在请求后端，类似于，和浏览器说声，我给发消息了，你用Ajax收一下。
        webSocketChannelPool.sendToUser(userId, WsBean.get(WsBean.CallBackEm.receive_msg));

        return AjaxBean.getOkData(body);
    }

    /**
     * 获取聊天记录
     * @param userId 和谁的聊天记录
     * @return 信息实体
     */
    public AjaxBean userClick(String userId){
        // 这里分两次查，第一次查自己发的，第二次查ta发的
        String thisUserId = StpUtil.getLoginIdAsString();
        ArrayList<ImChatRecord> allImChatList = new ArrayList<>(imChatRecordService.lambdaQuery()
                .eq(ImChatRecord::getSendUserId, thisUserId)
                .eq(ImChatRecord::getReceiveUserId, userId)
                .list());

        allImChatList.addAll(imChatRecordService.lambdaQuery()
                .eq(ImChatRecord::getSendUserId, userId)
                .eq(ImChatRecord::getReceiveUserId, thisUserId)
                .list());
        // 查看聊天中的图片
        ArrayList<String> imgList = new ArrayList<>();
        // 组合一下，
        List<ImChatRecord> imChatRecords = allImChatList.stream().sorted(Comparator.comparing(ImChatRecord::getId)).toList();
        ArrayList<MsgBody> list = new ArrayList<>();
        for (ImChatRecord record : imChatRecords) {
            MsgBody msgBody = JSON.parseObject(record.getMsgBody(), MsgBody.class);
            msgBody.setId(record.getId());
            if (record.getSendUserId().equals(thisUserId)){
                msgBody.setType(MsgBody.Type.self);
            } else {
                msgBody.setType(MsgBody.Type.other);
            }
            if (msgBody.getMsgType() == MsgBody.MsgType.img) {
                imgList.add(msgBody.getMsgContent());
            }

            list.add(msgBody);
            // 将消息设为已读
            ImChatRecord updateBean = new ImChatRecord();
            updateBean.setId(record.getId());
            updateBean.setReading(true);
            imChatRecordService.updateById(updateBean);
        }
        // 点击查看过后将消息设置为已读状态
        return AjaxBean.getOkData(list).set("imgList",imgList);
    }
}
